package com.yanqu.road.server.manger.wingroom;

import com.yanqu.road.dao.impl.wingroom.chakra.WingRoomChakraBeVisitNumDaoImpl;
import com.yanqu.road.dao.impl.wingroom.chakra.WingRoomChakraBeVisitRecordDaoImpl;
import com.yanqu.road.dao.impl.wingroom.chakra.WingRoomChakraDaoImpl;
import com.yanqu.road.dao.impl.wingroom.chakra.WingRoomChakraDetailDaoImpl;
import com.yanqu.road.entity.config.badge.BadgeConfig;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.LogWingRoomChakraVisit;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.entity.wingroom.chakra.WingRoomChakraPatronsAddItem;
import com.yanqu.road.entity.wingroom.chakra.data.UserWingRoomChakra;
import com.yanqu.road.entity.wingroom.chakra.data.UserWingRoomChakraBeVisitNum;
import com.yanqu.road.entity.wingroom.chakra.data.UserWingRoomChakraBeVisitRecord;
import com.yanqu.road.entity.wingroom.chakra.data.UserWingRoomChakraDetail;
import com.yanqu.road.entity.wingroom.chakra.enums.WingRoomPositionTypeEnum;
import com.yanqu.road.exception.BusinessException;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.WingRoomChakraProto.WingRoomChakraProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PreReduceModule;
import com.yanqu.road.server.gameplayer.module.wingroom.WingRoomChakraModule;
import com.yanqu.road.server.manger.config.BadgeConfigMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.pb.WingRoomChakraPb;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WingRoomChakraMgr extends TempMgr {

    //玩家被拜访次数MAP
    private static Map<Long, UserWingRoomChakraBeVisitNum> beVisitNumMap = new ConcurrentHashMap<>();

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        WingRoomChakraBeVisitNumDaoImpl beVisitNumDao = new WingRoomChakraBeVisitNumDaoImpl();
        beVisitNumMap = beVisitNumDao.getUserWingRoomChakraBeVisitNumMap();
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        //被拜访次数记录
        WingRoomChakraBeVisitNumDaoImpl beVisitNumDao = new WingRoomChakraBeVisitNumDaoImpl();
        for (UserWingRoomChakraBeVisitNum beVisitNumRecord : beVisitNumMap.values()) {
            if (beVisitNumRecord.isInsertOption()) {
                beVisitNumDao.add(beVisitNumRecord);
            } else if (beVisitNumRecord.isUpdateOption()) {
                beVisitNumDao.update(beVisitNumRecord);
            }
        }
        return true;
    }

    /**
     * 获取被拜访的次数
     * @param userId
     * @return
     */
    public static int getBeVisitNum(long userId) {
        UserWingRoomChakraBeVisitNum wingRoomChakraVisitNum = beVisitNumMap.get(userId);
        if (wingRoomChakraVisitNum != null) {
            return wingRoomChakraVisitNum.getBeVisitNum();
        }
        return 0;
    }

    /**
     * 获取拜访奖励
     * @param windWaterLevel
     * @return
     */
    public static Property getVisitReward(int windWaterLevel) {
        String config = GameConfig.CHAKRAS_VISIT_REWARD;
        if (StringUtils.isNullOrEmpty(config)) {
            return null;
        }
        int rewardNum = 0;
        String[] configStrArr = config.split("\\|");
        for (String configStr : configStrArr) {
            String[] cConfigStrArr = configStr.split("#");
            //奖励
            String[] rewardStrArr = cConfigStrArr[0].split(",");
            int minReward = Integer.parseInt(rewardStrArr[0]);
            int maxReward = Integer.parseInt(rewardStrArr[1]);
            //等级
            String[] leveStrArr = cConfigStrArr[1].split(";");
            int minLevel = Integer.parseInt(leveStrArr[0]);
            int maxLevel = Integer.parseInt(leveStrArr[1]);
            //判断等级命中
            if (windWaterLevel >= minLevel && windWaterLevel<= maxLevel) {
                //随机出奖励
                RandomHelper randomHelper = new RandomHelper();
                rewardNum = randomHelper.next(minReward, maxReward + 1);
                break;
            }
        }
        Property reward = new Property();
        reward.setGood(GameConfig.CHAKRAS_WIND_WATER_DEBRIS_PROP_ID, BigInteger.valueOf(rewardNum));
        return reward;
    }

    /**
     * 拜访
     * @param player
     * @param reqMsg
     * @throws BusinessException
     */
    public static void visitUser(GamePlayer player, WingRoomChakraProto.WingRoomChakraVisitReqMsg reqMsg) throws BusinessException{
        long beVisitUserId = reqMsg.getBeVisitUserId();
        long beVisitServerId = reqMsg.getBeVisitServerId();
        //判断自己命盘是否解锁
        if (!SystemOpenMgr.checkSystemOpen(player.getUserId(), eSystemId.WingRoom.getValue())) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_NOT_UNLOCK);
        }
        //判断是否拜访过
        int visitNum = player.getModule(WingRoomChakraModule.class).getDailyVisitUserNum(beVisitUserId);
        if (visitNum >= GameConfig.CHAKRAS_DAILY_USE_LIMIT) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_TODAY_VISITED_USER);
        }
        //判断是本服还是跨服
        if (GameServer.getInstance().getServerId() == beVisitServerId) {
            localVisitUser(player, beVisitUserId);
        } else {
            crossVisitUser(player, beVisitUserId, beVisitServerId);
        }
    }

    /**
     * 本服拜访
     * @param player
     * @param beVisitUserId
     * @throws BusinessException
     */
    public static void localVisitUser(GamePlayer player, long beVisitUserId) throws BusinessException {
        WingRoomChakraModule wingRoomChakraModule = player.getModule(WingRoomChakraModule.class);
        //判断对方系统是否解锁
        if (!SystemOpenMgr.checkSystemOpen(beVisitUserId, eSystemId.WingRoom.getValue())) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_VISIT_SYSTEM_NOT_UNLOCK);
        }
        //判断对方加成是否达到上限
        if (getBeVisitNum(beVisitUserId) >= GameConfig.CHAKRAS_VISIT_MAX_COUNT) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_TARGET_BE_VISIT_ADD_LIMIT);
        }
        //对方厢房数据
        UserWingRoomChakra beVisitUserWingRoomChakra = getUserChakraData(beVisitUserId);
        if (beVisitUserWingRoomChakra == null) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_VISIT_TARGET_DATA_NOT_INIT);
        }
        //判断道具是否足够
        Property property = new Property();
        property.setGood(GameConfig.CHAKRAS_VISIT_PROP_ID, BigInteger.ONE);
        boolean usePropFlag = player.getModule(CurrencyModule.class).removeCurrency(property, eLogMoneyType.WingRoomChakra, eLogMoneyType.WingRoomChakraVisitPropCost);
        if (!usePropFlag) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_VISIT_PROP_NOT_ENOUGH);
        }
        //增加拜访他人次数
        wingRoomChakraModule.addDailyVisitUserNum(beVisitUserId);
        //拜访处理
        UserBaseInfo userBaseInfo = UserMgr.getUserBaseInfo(player.getUserId(), GameServer.getInstance().getServerId());
        successVisitUser(player.getUserId(), userBaseInfo, beVisitUserId);
        //添加拜访奖励
        Property reward = getVisitReward(beVisitUserWingRoomChakra.getWindWaterLevel());
        if (reward != null) {
            player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.WingRoomChakra, eLogMoneyType.WingRoomChakraVisitPropReward);
        }

        //日志
        LogWingRoomChakraVisit logWingRoomChakraVisit = new LogWingRoomChakraVisit();
        logWingRoomChakraVisit.setUserId(player.getUserId());
        logWingRoomChakraVisit.setBeVisitUserId(beVisitUserId);
        logWingRoomChakraVisit.setBeVisitServerId(GameServer.getInstance().getServerId());
        logWingRoomChakraVisit.setReward(PropertyHelper.parsePropertyToString(reward));
        logWingRoomChakraVisit.setBeVisitAddRate(GameConfig.CHAKRAS_VISIT_EFFECT);
        AutoLogMgr.add(logWingRoomChakraVisit);

        //返回PB
        WingRoomChakraProto.WingRoomChakraVisitRespMsg.Builder respMsg = WingRoomChakraProto.WingRoomChakraVisitRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        respMsg.addAllVisitNumList(WingRoomChakraPb.buildVisitNumList(wingRoomChakraModule.getDailyVisitUserNumMap()));
        respMsg.setBeVisitUserAddRate(getVisitWindWaterAddRate(beVisitUserId));
        player.sendPacket(Protocol.U_CHAKRA_VISIT, respMsg);
    }

    /**
     * 跨服拜访
     * @param player
     * @param beVisitUserId
     * @param beVisitServerId
     * @throws BusinessException
     */
    public static void crossVisitUser(GamePlayer player, long beVisitUserId, long beVisitServerId) throws BusinessException {
        //判断道具是否足够
        Property property = new Property();
        property.setGood(GameConfig.CHAKRAS_VISIT_PROP_ID, BigInteger.ONE);
        boolean usePropFlag = player.getModule(CurrencyModule.class).currencyIsEnough(property);
        if (!usePropFlag) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_VISIT_PROP_NOT_ENOUGH);
        }
        //预扣道具
        player.getModule(PreReduceModule.class).preReduce(property);
        //发送请求到跨服
        WingRoomChakraProto.WingRoomChakraCrossVisitReqMsg.Builder reqMsg = WingRoomChakraProto.WingRoomChakraCrossVisitReqMsg.newBuilder();
        reqMsg.setBeVisitUserId(beVisitUserId);
        reqMsg.setBeVisitServerId(beVisitServerId);
        UserBaseInfo userBaseInfo = UserMgr.getUserBaseInfo(player.getUserId(), GameServer.getInstance().getServerId());
        reqMsg.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        player.sendPacket(CrossProtocol.C_CROSS_WING_ROOM_CHAKRA_VISIT, reqMsg);
    }

    /**
     * 跨服拜访处理
     * @param reqMsg
     * @throws BusinessException
     */
    public static UserWingRoomChakra crossVisitHandle(WingRoomChakraProto.WingRoomChakraVisitFromCrossReqMsg reqMsg) throws BusinessException{
        long beVisitUserId = reqMsg.getBeVisitUserId();
        //判断系统是否解锁
        if (!SystemOpenMgr.checkSystemOpen(beVisitUserId, eSystemId.WingRoom.getValue())) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_VISIT_SYSTEM_NOT_UNLOCK);
        }
        //判断对方加成是否达到上限
        if (getBeVisitNum(beVisitUserId) >= GameConfig.CHAKRAS_VISIT_MAX_COUNT) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_TARGET_BE_VISIT_ADD_LIMIT);
        }
        //对方厢房数据
        UserWingRoomChakra beVisitUserWingRoomChakra = getUserChakraData(beVisitUserId);
        if (beVisitUserWingRoomChakra == null) {
            throw BusinessException.newException(GameErrorCode.E_CHAKRA_VISIT_TARGET_DATA_NOT_INIT);
        }
        //拜访成功处理
        UserBaseInfo visitUserBaseInfo = PlayerBasePb.parseToUserBaseInfo(reqMsg.getVisitPlayerBaseData());
        successVisitUser(reqMsg.getVisitUserId(), visitUserBaseInfo, reqMsg.getBeVisitUserId());
        return beVisitUserWingRoomChakra;
    }

    /**
     * 跨服拜访返回处理
     * @param reqMsg
     * @return
     */
    public static void crossVisitReturnHandle(WingRoomChakraProto.WingRoomChakraBeVisitFromCrossReqMsg reqMsg) {
        WingRoomChakraProto.WingRoomChakraVisitRespMsg.Builder respMsg = WingRoomChakraProto.WingRoomChakraVisitRespMsg.newBuilder();
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(reqMsg.getVisitUserId());
        //撤销预扣除道具
        Property cost = new Property(GameConfig.CHAKRAS_VISIT_PROP_ID, BigInteger.ONE);
        player.getModule(PreReduceModule.class).restorePreReduce(cost);
        //判断是否成功
        if (reqMsg.getRet() != 0) {
            //返回PB
            respMsg.setRet(reqMsg.getRet());
            player.sendPacket(Protocol.U_CHAKRA_VISIT, respMsg);
            return;
        }
        //真正扣除
        player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.WingRoomChakra, eLogMoneyType.WingRoomChakraVisitPropCost);
        //增加拜访次数
        player.getModule(WingRoomChakraModule.class).addDailyVisitUserNum(reqMsg.getBeVisitUserId());
        //添加拜访奖励
        Property reward = getVisitReward(reqMsg.getBeVisitWindWaterLevel());
        if (reward != null) {
            player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.WingRoomChakra, eLogMoneyType.WingRoomChakraVisitPropReward);
        }

        //日志
        LogWingRoomChakraVisit logWingRoomChakraVisit = new LogWingRoomChakraVisit();
        logWingRoomChakraVisit.setUserId(player.getUserId());
        logWingRoomChakraVisit.setBeVisitUserId(reqMsg.getBeVisitUserId());
        logWingRoomChakraVisit.setBeVisitServerId(reqMsg.getBeVisitServerId());
        logWingRoomChakraVisit.setReward(PropertyHelper.parsePropertyToString(reward));
        logWingRoomChakraVisit.setBeVisitAddRate(GameConfig.CHAKRAS_VISIT_EFFECT);
        AutoLogMgr.add(logWingRoomChakraVisit);

        //返回PB
        respMsg.setRet(0);
        respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        respMsg.addAllVisitNumList(WingRoomChakraPb.buildVisitNumList(player.getModule(WingRoomChakraModule.class).getDailyVisitUserNumMap()));
        respMsg.setBeVisitUserAddRate(reqMsg.getBeVisitAddRate());
        player.sendPacket(Protocol.U_CHAKRA_VISIT, respMsg);
    }

    /**
     * 拜访成功处理
     * @param beVisitUserId 被拜访的玩家ID
     */
    public static void successVisitUser(long userId, UserBaseInfo userBaseInfo, long beVisitUserId) {
        //增加对方被拜访次数
        UserWingRoomChakraBeVisitNum beVisitNumInfo = beVisitNumMap.get(beVisitUserId);
        if (beVisitNumInfo == null) {
            beVisitNumInfo = new UserWingRoomChakraBeVisitNum(beVisitUserId, 1, System.currentTimeMillis());
            beVisitNumInfo.setInsertOption();
            beVisitNumMap.put(beVisitNumInfo.getUserId(), beVisitNumInfo);
        } else {
            beVisitNumInfo.addBeVisitNum(1);
            if (beVisitNumInfo.getBeVisitNum() == 1) {
                beVisitNumInfo.setLastRecoverTime(System.currentTimeMillis());
            }
        }
        //判断被拜访玩家是否在线
        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(beVisitUserId);
        if (gamePlayer != null) {
            //被拜访记录
            gamePlayer.getModule(WingRoomChakraModule.class).addBeVisitRecord(userId, userBaseInfo);
        } else {
            //玩家不在线，数据库添加被拜访记录
            UserWingRoomChakraBeVisitRecord record = new UserWingRoomChakraBeVisitRecord();
            record.setUserId(beVisitUserId);
            record.setVisitUserId(userId);
            record.setVisitUserInfo(userBaseInfo);
            record.setCreateTime(System.currentTimeMillis());
            new WingRoomChakraBeVisitRecordDaoImpl().add(record);
            //榜单刷新
            changeWindWaterRankOffline(beVisitUserId);
        }
    }

    /**
     * 排行变动
     */
    private static void changeWindWaterRankOffline(long userId) {
        try {
            //查询风水数据
            UserWingRoomChakra userWingRoomChakra = new WingRoomChakraDaoImpl().getUserWingRoomChakra(userId);
            long windWater = userWingRoomChakra.getRealWindWater();
            //获取风水增加比例
            int windWaterAddRate = WingRoomChakraMgr.getVisitWindWaterAddRate(userId);
            BigDecimal rate = BigDecimal.valueOf(windWaterAddRate).divide(BigDecimal.valueOf(1000));
            BigDecimal addWindWater = BigDecimal.valueOf(windWater).multiply(rate);
            long totalWindWater = windWater + addWindWater.setScale(0, RoundingMode.UP).longValue();
            //更新排行
            RankMgr.changeUserRank(eBigRankType.Normal.getValue(), userId, BigInteger.valueOf(totalWindWater), eRankType.WingRoomWindWaterValue.getValue(), "");
        } catch (Exception ex) {
            getLogger().error(ex);
        }
    }

    /**
     * 获取拜访风水加成千分比
     * @param userId
     * @return
     */
    public static int getVisitWindWaterAddRate(long userId) {
        int visitNum = WingRoomChakraMgr.getBeVisitNum(userId);
        int useVisitNum = Math.min(visitNum, GameConfig.CHAKRAS_VISIT_MAX_COUNT);
        return GameConfig.CHAKRAS_VISIT_EFFECT * useVisitNum;
    }

    /**
     * 拜访加成恢复check
     */
    public static void checkBeVisitNumRecover() {
        long now = System.currentTimeMillis();
        for (UserWingRoomChakraBeVisitNum beVisitNumInfo : beVisitNumMap.values()) {
            if (beVisitNumInfo.getBeVisitNum() > 0 && now - beVisitNumInfo.getLastRecoverTime() >= GameConfig.CHAKRAS_VISIT_EFFECT_TIME * DateHelper.SECOND_MILLIONS) {
                beVisitNumInfo.setBeVisitNum(beVisitNumInfo.getBeVisitNum() - 1);
                beVisitNumInfo.setLastRecoverTime(beVisitNumInfo.getLastRecoverTime() + GameConfig.CHAKRAS_VISIT_EFFECT_TIME * DateHelper.SECOND_MILLIONS);
                //同步
                GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(beVisitNumInfo.getUserId());
                if (gamePlayer != null) {
                    //在线
                    //排行变化
                    gamePlayer.getModule(WingRoomChakraModule.class).changeWindWaterRank();
                    //同步
                    gamePlayer.getModule(WingRoomChakraModule.class).syncData();
                } else {
                    //不在线
                    //排行变化
                    changeWindWaterRankOffline(beVisitNumInfo.getUserId());
                }
            }
        }
    }

    /**
     * 获取门客加成MAP
     * @param userId 玩家ID
     * @param wingRoomPositionTypeEnum 1:加资质，2：加赚钱千分比
     * @return K:门客ID,V:加成值
     */
    public static Map<Integer, Long> getPatronsAddValueMap(long userId, WingRoomPositionTypeEnum wingRoomPositionTypeEnum) {
        Map<Integer, Map<Integer, Map<Integer, UserWingRoomChakraDetail>>> chakraDetailMap;
        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(userId);
        if (gamePlayer != null) {
            //存在，读内存
            chakraDetailMap = gamePlayer.getModule(WingRoomChakraModule.class).getUserWingRoomChakraDetailMap();
        } else {
            //不存在，读库
            chakraDetailMap = new WingRoomChakraDetailDaoImpl().getUserWingRoomChakraDetailMap(userId);
        }
        //获取赚钱加成
        Map<Integer, Long> map = new ConcurrentHashMap<>();
        for (Map<Integer, Map<Integer, UserWingRoomChakraDetail>> typeMap : chakraDetailMap.values()) {
            for (Map<Integer, UserWingRoomChakraDetail> positionMap : typeMap.values()) {
                for (UserWingRoomChakraDetail chakraDetail : positionMap.values()) {
                    for (WingRoomChakraPatronsAddItem item : chakraDetail.getPatronsList()) {
                        if (item.getType() == wingRoomPositionTypeEnum.getType()) {
                            Long oldValue = map.get(item.getPatronsId());
                            long addValue;
                            if (oldValue != null) {
                                addValue = oldValue + item.getAddValue();
                            } else {
                                addValue = item.getAddValue();
                            }
                            map.put(item.getPatronsId(), addValue);
                        }
                    }
                }
            }
        }
        return map;
    }

    /**
     * 判断命盘解锁，需要的命盘等级
     * @param index 命盘下标
     * @return
     */
    public static int getChakraUnlockLevel(int index) {
        String[] unlockLevelArr = GameConfig.CHAKRAS_UNLOCK_PARAM.split(";");
        int i = 1;
        for (String unlockLevelStr : unlockLevelArr) {
            int unlockLevel = Integer.parseInt(unlockLevelStr);
            if (i == index) {
                return unlockLevel;
            }
            i++;
        }
        return 99999;
    }

    /**
     * 获取玩家命盘基础数据，玩家不在线读库
     * @param userId
     * @return
     */
    public static UserWingRoomChakra getUserChakraData(long userId) {
        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(userId);
        if (gamePlayer != null) {
            return gamePlayer.getModule(WingRoomChakraModule.class).getUserWingRoomChakra();
        } else {
            return new WingRoomChakraDaoImpl().getUserWingRoomChakra(userId);
        }
    }
}
